package org.finesys.common.security.core.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

import javax.servlet.http.HttpServletRequest;

import org.finesys.common.constants.SecurityConstants;
import org.finesys.common.core.util.WebUtil;
import org.finesys.common.security.core.constant.TenantConstants;
import org.finesys.common.security.core.module.AuthUser;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.security.web.authentication.www.BasicAuthenticationConverter;
import org.springframework.util.StringUtils;

import cn.hutool.core.text.CharSequenceUtil;
import lombok.SneakyThrows;
import lombok.experimental.UtilityClass;

/**
 * 获取权限用户信息工具类
 */
@UtilityClass
public class SecurityUtils {

    /**
     * 获取认证用户信息
     */
    public Authentication getAuthentication() {
        return SecurityContextHolder.getContext().getAuthentication();
    }

    /**
     * 获取用户
     */
    public AuthUser getUser() {
        Authentication authentication = getAuthentication();
        if (authentication == null) {
            return null;
        }
        return getUser(authentication);
    }

    public String getUserId() {
        AuthUser user = getUser();
        if (Objects.isNull(user)) {
            return null;
        }
        return String.valueOf(user.getUserId());
    }

    /**
     * 获取用户
     */
    public AuthUser getUser(Authentication authentication) {
        Object principal = authentication.getPrincipal();
        if (principal instanceof AuthUser) {
            return (AuthUser) principal;
        }
        return null;
    }

    /**
     * 获取用户角色信息
     *
     * @return 角色集合
     */
    public List<Long> getRoles() {
        Authentication authentication = getAuthentication();
        Collection<? extends GrantedAuthority> authories = authentication.getAuthorities();
        List<Long> roles = new ArrayList<>();
        authories.stream()
                .filter(s -> CharSequenceUtil.startWith(s.getAuthority(), SecurityConstants.ROLE))
                .forEach(s -> {
                    String id = CharSequenceUtil.removePrefix(s.getAuthority(), SecurityConstants.ROLE);
                    roles.add(Long.parseLong(id));
                });
        return roles;
    }

    /**
     * 获取客户端ID
     * <p>
     * 兼容两种方式获取OAuth2客户端信息（client_id、client_secret） <br/>
     * 方式一：client_id、client_secret放在请求路径中 <br/>
     * 方式二：放在请求头（Request Headers）中的Authorization字段，且经过加密，例如 Basic Y2xpZW50OnNlY3JldA==
     * 明文等于 client:secret
     */
    @SneakyThrows
    public String getClientId() {
        HttpServletRequest request = WebUtil.getRequest().get();
        BasicAuthenticationConverter converter = new BasicAuthenticationConverter();

        return converter.convert(request).getName();
    }

    public String getGrantType() {
        HttpServletRequest request = WebUtil.getRequest().get();
        // 从请求路径中获取
        return request.getParameter(OAuth2ParameterNames.GRANT_TYPE);
    }

    /**
     * 获取请求中携带的租户id
     *
     * @return 租户id
     */
    public static Long getTenantId(HttpServletRequest request) {
        String header = request.getHeader(TenantConstants.TENTANT_ID);
        if(StringUtils.hasText(header)){
            return Long.valueOf(header);
        }
        String parameter = request.getParameter(TenantConstants.TENTANT_ID);
        if(StringUtils.hasText(parameter)){
            return Long.valueOf(parameter);
        }
        return null;
    }

    public static Collection<? extends GrantedAuthority> getAuthorities() {
        Authentication authentication = getAuthentication();
        return authentication.getAuthorities();
    }
}
